﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;


namespace PBRSystem.Coord
{
    public class PBRBounds3
    {
        #region Variables
        private PBRPoint3 _pMin, _pMax;
        #endregion

        #region Reporter
        public PBRPoint3 PMin { get => _pMin; set => _pMin = value; }
        public PBRPoint3 PMax { get => _pMax; set => _pMax = value; }
        #endregion

        #region Contructor
        public PBRBounds3()
        {
            _pMin = new PBRPoint3(0, 0, 0);
            _pMax = new PBRPoint3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
        }

        public PBRBounds3(PBRPoint3 p)
        {
            _pMin = new PBRPoint3(p);
            _pMax = new PBRPoint3(p);
        }

        public PBRBounds3(PBRPoint3 p0, PBRPoint3 p1)
        {
            _pMin = new PBRPoint3(p0);
            _pMax = new PBRPoint3(p1);
        }

        #endregion

        #region Operator

        public static bool operator ==(PBRBounds3 a, PBRBounds3 b)
        {
            return (a.PMax == b.PMax) && (a.PMin == b.PMin);
        }

        public static bool operator !=(PBRBounds3 a, PBRBounds3 b)
        {
            return (a.PMax != b.PMax) || (a.PMin != b.PMin);
        }
        #endregion

        #region Override
        public override bool Equals(object obj)
        {
            if(!(obj is PBRBounds3))
            {
                return false;
            }

            PBRBounds3 b = (PBRBounds3)obj;
            return (b.PMin == _pMin) && (b.PMax == _pMax);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        #endregion

        #region Operation
        public PBRVector3 Diagonal()
        {
            return _pMax - _pMin;
        }
        
        public float SurfaceArea()
        {
            PBRVector3 d = Diagonal();
            return 2 * (d.X * d.Y + d.X * d.Z + d.Y * d.Z);
        }
        
        public float Volume()
        {
            PBRVector3 d = Diagonal();
            return d.X * d.Y * d.Z;
        }

        public int MaximumExtent()
        {
            PBRVector3 d = Diagonal();
            if(d.X > d.Y && d.X > d.Z)
            {
                return 0;
            }else if(d.Y > d.Z)
            {
                return 1;
            }
            else
            {
                return 2;
            }
        }

        public static bool Overlaps(PBRPoint3 p, PBRBounds3 b)
        {
            return (p.X >= b.PMin.X && p.X <= b.PMax.X) &&
                    (p.Y >= b.PMin.Y && p.Y <= b.PMax.Y) &&
                    (p.Z >= b.PMin.Z && p.Z <= b.PMax.Z);
        }

        public static bool Inside(PBRBounds3 b, PBRPoint3 p)
        {
            return (p.X >= b.PMin.X && p.X <= b.PMax.X) &&
                   (p.Y >= b.PMin.Y && p.Y <= b.PMax.Y) &&
                   (p.Z >= b.PMin.Z && p.Z <= b.PMax.Z);
        }

        public static bool InsideExclusive(PBRBounds3 b, PBRPoint3 p)
        {
            return (p.X >= b.PMin.X && p.X < b.PMax.X) &&
                   (p.Y >= b.PMin.Y && p.Y < b.PMax.Y) &&
                   (p.Z >= b.PMin.Z && p.Z < b.PMax.Z);
        }




        #endregion


    }
}


